#include <iostream>
#include <string.h>

using std::cout;
using std::endl;
using std::string;

//1、派生里没有拷贝构造、赋值运算符函数时，会自动调用基类的这两个
//2、如果有，则不再自动调用。要用时则自己写出来：
//        则默认 派生类拷贝=基类无参+派生类拷贝，需要自己写成 基类拷贝+派生类拷贝
//        则默认 派生类赋值=派生类赋值         ，需要自己写成 基类赋值+派生类赋值
class Base{
public:
    Base()
    : _pbase(nullptr)
    {
        cout<<"Base无参构造"<<endl;
    }
    Base(const char *pstr)
    : _pbase(new char[strlen(pstr)+1]())
    {
        strcpy(_pbase,pstr);
        cout<<"Base有参构造"<<endl;
    }

    Base(const Base &rhs)
    : _pbase(new char[strlen(rhs._pbase)+1]())
    {
        strcpy(_pbase,rhs._pbase);
        cout<<"Base拷贝"<<endl;
    }

    Base &operator=(const Base &rhs){
        cout<<"Base赋值"<<endl;
        if(this != &rhs){
            delete []_pbase;
            _pbase=nullptr;

            _pbase=new char[strlen(rhs._pbase)+1]();
            strcpy(_pbase,rhs._pbase);
        }
        return *this;

    }

    ~Base(){
        cout<<"~Base()"<<endl;
        if(_pbase){
            delete []_pbase;
            _pbase=nullptr;
        }
    }

    friend std::ostream &operator<<(std::ostream &os, const Base &rhs);

private:
    char *_pbase;
};

std::ostream &operator<<(std::ostream &os, const Base &rhs){
    if(rhs._pbase){
        os<<rhs._pbase;
    }
    return os;
}

class Deriver
: public Base
{
public:
    Deriver(const char *pbase, const char *pderived)
    : Base(pbase)
    , _pderived(new char[strlen(pderived)+1]())
    {
        cout<<"Deriver有参构造"<<endl;
        strcpy(_pderived,pderived);
    }

    Deriver(const Deriver &rhs)
    : Base(rhs) 
    // 传入的参数是Deriver类型，那么也只有const Base &rhs能接受，即基类拷贝
    // 函数调用不必在乎private成员，只有直接访问时才去关注
    
    , _pderived(new char[strlen(rhs._pderived)+1]())
    {
        cout<<"Deriver拷贝"<<endl;
        strcpy(_pderived,rhs._pderived);
    }

    Deriver &operator=(const Deriver &rhs){
        cout<<"Deriver赋值"<<endl;
        if(this != &rhs){
            //显式执行基类赋值
            Base::operator=(rhs);

            delete []_pderived;
            _pderived=nullptr;

            _pderived=new char[strlen(rhs._pderived)+1]();
            strcpy(_pderived,rhs._pderived);
        }
        return *this;
    }

    ~Deriver(){
        cout<<"~Deriver()"<<endl;
        if(_pderived){
            delete []_pderived;
            _pderived=nullptr;
        }
    }

    friend std::ostream &operator<<(std::ostream &os, const Deriver &rhs);

private:
    char *_pderived;
};

std::ostream &operator<<(std::ostream &os, const Deriver &rhs){
    const Base &ref=rhs;
    if(rhs._pderived){
    os<<ref                     
        <<","<<rhs._pderived;    
    }
    return os;
}

void test(){
    Deriver der1("hello","world");
    cout<<der1<<endl;

    cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;

    Deriver der2=der1;
    cout<<der2<<endl;
    cout<<endl;
    Deriver der4(der1);
    cout<<der4<<endl;

    cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;

    Deriver der3("hubei","wuhan");
    cout<<der3<<endl;

    cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;

    der3=der1;
    cout<<der1<<endl;
    cout<<der3<<endl;

    cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
}
int main()
{   
    test();
    return 0;
}

